Skip to content

[pull] canary from vercel:canary - #1322

Merged
pull[bot] merged 6 commits into
code:canaryfrom
vercel:canary
Aug 20, 2026
Merged

[pull] canary from vercel:canary#1322
pull[bot] merged 6 commits into
code:canaryfrom
vercel:canary

Conversation

@pull

@pull pull Bot commented Aug 20, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

icyJoseph and others added 6 commits August 20, 2026 15:26
Completing the input-output pair for cached functions.

This is addressing user confusion around what happens to a cached
function, and functions within the scope.
Scaffolds a new API, `unstable_navigation()`. It's only allowed in
server code, so we ban it from being imported in the client.
Implementation follows upstack. Intended to be merged together.
`navigation()` is a new API that allows omitting contents from runtime
shells and runtime prefetches. Conceptually, the point is to express
that something is expensive to compute, so we shouldn't do it for
requests that may not get used (shells and prefetches). Notably, this
means that it's fine to include it in a static prerender -- it'll be
computed once and used for many requests, so it doesn't make sense to
exclude it.



## Implementation

The split in behavior across static and runtime prerenders is a
departure from how most of our APIs behave -- usually, if something
resolves statically, then it also resolves in "more complete" prerender.
Departing from this leads to some implementation complexity.

We include three new stages, used by two facets of the implementation:

```diff
export enum RenderStage {
  Before = 1,
  //
  ShellStatic = 10,
+ PrefetchStatic = 11, <------- params, prefetch()  [static prerenders]
+ NavigationStatic = 12  <------navigation()        [static prerenders]
  Static = 13, <--------------- finish accumulators [static prerenders]
  //
  ShellRuntime = 20,
  Runtime = 21, <-------------- params, prefetch() [runtime prerenders]
+ NavigationRuntime = 22, <---- navigation()       [runtime prerenders]
  //
  Dynamic = 30,
  Abandoned = 40,
}
```

### NavigationRuntime

In runtime prerenders (or dev renders that simulate them),
`navigation()` resolves in `NavigationRuntime`
We only reach this stage in 1. the embedded runtime prerender produced
for Cached Navigations and 2. during dev/prod full staged renders --
runtime shells end in `ShellRuntime`, and runtime prefetches end in
`Runtime`.

Notably, this means that content gated behind `navigation()` is included
in the embedded runtime prefetch stream.

### PrefetchStatic & NavigationStatic

This is a helper stage added before `Static`. Static prefetches still
use the `Static` stage for their output. This new stage exists so that
we can resolve static `params` (and `prefetch()` when we implement it)
which the stage is named after) separately from `navigation()`, which
resolves in `NavigationStatic`, after which the prerender ends in
`Static`. This separation is important, because during static prerenders
we track whether or not runtime APIs are used (see
`trackRuntimeDataAccessed`) to determine if a runtime shell (or runtime
prefetch) might give us more content than the static ones. However, a
runtime shell/prefethc **would not resolve navigation()**, so `await
navigation(); await cookies()` would not reveal more content, and thus
shouldn't count as a usage that prevents static optimization.
We achieve this by checking the stage inside
`trackRuntimeDataAccessedImpl` and not tracking anything if we reached
the `NavigationStatic` stage.

### Behavior of shells and validation

As noted before, `navigation()` has an incompatible resolution order
between static and runtime prerenders. In #97040, we did some groundwork
to deal with this in validation.

Static prerenders resolve `navigation()`, which means that static shells
include content gated behind navigation(). This means that Static Shell
Validation allows them.

On the other hand, App shells **do not** resolve `navigation()`. This
leads to an inconsistency for Instant Validation -- a `await
navigation()` might be fine if a page is prefetched statically, but
would become blocking as soon as the page starts using runtime data and
switches to a runtime shell. To avoid this pitfall, we pessimistically
assume that any `navigation()` _might_ be part of a runtime
shell/prefetch, so any `navigation()` unguarded by Suspense will error
in IV.

In practice, this is handled analogously to static params: we do a dev
render with `needsAppShell: true`, which makes `navigation()` resolve in
`NavigationRuntime`, and then we use the `ShellRuntime` stage when
validating, which means that `navigation()` will be a hole. Note that
the discriminated error message logic currently only retries errors
using the `Runtime` stage, which won't have `navigation()` resolved
either, so it will be incorrectly reported as dynamic data. This will be
improved in a follow up.
#97360)

Relocates `useDynamicRouteParams` and `useDynamicSearchParams` to avoid
having to update `client-hook-abort-reasons.test.ts` every time there's
changes in `dynamic-rendering.ts`. Webpack leaked the source location of
the `React.use` calls inside, so any code change that moved the source
of the hook would require a snapshot update.

For reasons i don't quite understand, moving the hooks to a different
file improved the ignore-listing, i.e. we no longer point to the
internals of the hooks. This is surprising but not unwelcome.
Consistent naming:
- `"use turbopack no side effects"`
- `"use turbopack: constants"`
Co-authored-by: next-js-bot[bot] <279046576+next-js-bot[bot]@users.noreply.github.com>
@pull pull Bot locked and limited conversation to collaborators Aug 20, 2026
@pull pull Bot added the ⤵️ pull label Aug 20, 2026
@pull
pull Bot merged commit 508e563 into code:canary Aug 20, 2026
15 of 20 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants